package com.cn.web.org.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cn.exception.MyException;
import com.cn.org.OrgDO;
import com.cn.page.PageVo;
import com.cn.upload.base.FileItemEntity;
import com.cn.user.UserDO;
import com.cn.user.UserUnitDO;
import com.cn.util.AuthUserContext;
import com.cn.util.GsonUtil;
import com.cn.util.JsonUtil;
import com.cn.util.SnowflakeIdWorkerUtil;
import com.cn.web.org.mapper.IOrgMapper;
import com.cn.web.org.service.OrgService;
import com.cn.web.org.vo.*;
import com.cn.web.user.service.UserService;
import com.cn.web.user.service.UserUnitService;
import com.cn.web.user.vo.UserSearch;
import com.cn.web.user.vo.UserVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * description: OrgService <br>
 * date: 21.12.16 14:56 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@Service
public class OrgServiceImpl implements OrgService {

    @Autowired
    private IOrgMapper orgMapper;

    @Autowired
    private UserUnitService userUnitService;

    @Autowired
    private UserService userService;


    @Override
    @Transactional
    public void add(OrgEditDTO edit) {
        UserDO token = AuthUserContext.get();
        OrgDO org = new OrgDO();
        BeanUtils.copyProperties(edit, org);
        if (edit.getFiles() != null) {
            org.setImgs(GsonUtil.toJson(edit.getFiles()));
        }
        if (StringUtils.isEmpty(org.getParentNo())) {
            org.setParentNo("0");
        }

        org.setAddId(token.getId().toString()).setAddName(token.getUserName());
        if (org.getId() == null || org.getId() <= 0) {
            org.setId(SnowflakeIdWorkerUtil.getId());
            org.setOrgNo(org.getId().toString());//设置为  主键ID
            this.orgMapper.insert(org);
        } else {
            this.orgMapper.update(org);
        }
    }

    @Override
    public OrgDO findId(String id) {
        return this.orgMapper.selectById(id);
    }

    @Override
    public OrgEditDTO find(String id, Boolean flag) {
        OrgDO orgEntity = this.findId(id);
        OrgEditDTO edit = new OrgEditDTO();
        BeanUtils.copyProperties(orgEntity, edit);
        if (StringUtils.isNotEmpty(orgEntity.getImgs())) {
            edit.setFiles(JSON.parseArray(orgEntity.getImgs(), FileItemEntity.class));
        }
        if (!flag) {
            OrgDO parent = findByParent(edit.getParentNo());
            if (parent != null) {
                edit.setParentName(parent.getOrgName());
            }
        }
        return edit;
    }

    @Override
    public OrgDO findByParent(String parentNo) {
        QueryWrapper<OrgDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("org_no", parentNo);
        return this.orgMapper.selectOne(queryWrapper);
    }

    @Override
    public PageInfo<OrgVO> page(PageVo<OrgSearch> pageVo) {
        return PageHelper.startPage(pageVo.getPageNum(), pageVo.getPageSize()).doSelectPageInfo(() -> {
            list(pageVo.getParam());
        });
    }

    @Override
    public List<OrgVO> list(OrgSearch search) {
        if (StringUtils.isEmpty(search.getOrgName())) {
            //树状结构
            List<OrgVO> data = this.orgMapper.list(search);
            if (data != null && data.size() > 0) {
                for (OrgVO t : data) {
                    search.setParentNo(t.getOrgNo());
                    t.setChild(list(search));
                }
            }
            return data;
        } else {
            search.setParentNo("");
            return this.orgMapper.list(search);
        }
    }

    @Override
    public List<OrgVO> listAllOrg(OrgSearch search) {
        return this.orgMapper.list(search);
    }


    @Override
    public void del(String id) {
        List<UserUnitDO> data = userUnitService.listByUnitId(id);
        if (data != null && data.size() > 0) {
            throw new MyException("该单位下存在用户，禁止删除！");
        }
        OrgDO org = this.findId(id);
        Map<String, Object> pd = new HashMap<>();
        pd.put("parent_no", org.getOrgNo());
        List<OrgDO> list = this.orgMapper.selectByMap(pd);
        if (list != null && list.size() > 0) {
            throw new MyException("该单位下存在下级单位，禁止删除！");
        }
        this.orgMapper.del(id);
    }

    @Override
    public List<OrgDO> listUnitByUserId(String userId) {
        return this.orgMapper.listUnitByUserId(userId);
    }

    @Override
    public Object packProcessUnitAndUserV2() {
        //所有部门
        List<OrgVO> orgs = this.listAllOrg(null);
        //所有人
        List<UserVO> users = listUsers2PackTree();
        Map<String /*单位ID*/, Map<String /*userId*/, UnitUserTreeV2VO>> userMap = new HashMap<>();
        users.forEach(t -> {
            UnitUserTreeV2VO u = new UnitUserTreeV2VO();
            u.setId(t.getId().toString()).setName(t.getUserName()).setUserId(u.getId());

            var units = t.getUnits();
            if (units != null && units.size() > 0) {
                for (UserVO.UserUnits unit : units) {
                    var tmpUserMap = userMap.get(unit.getId());
                    if (tmpUserMap == null) {
                        tmpUserMap = new HashMap<>();
                        userMap.put(unit.getId(), tmpUserMap);
                    }

                    var tmpUser = tmpUserMap.get(u.getId());
                    if (tmpUser == null) {
                        tmpUserMap.put(u.getId(), u);
                    }
                }
            }
        });

        List<UnitUserTreeV2VO> trees = new ArrayList<>();
        var root = orgs.stream().filter(t -> t.getParentNo().equalsIgnoreCase("0")).collect(Collectors.toList());
        if (root != null) {
            for (OrgVO r : root) {
                UnitUserTreeV2VO tree = new UnitUserTreeV2VO();
                tree.setId(r.getId().toString())
                        .setName(r.getOrgName())
                        .setParentId("0")
                ;
                packUser2TreeV2(tree, orgs, tree.getId(), userMap);

                trees.add(tree);
            }
        }
        return trees;
    }

    private void packUser2TreeV2(UnitUserTreeV2VO tree, List<OrgVO> orgs, String parentId, Map<String, Map<String, UnitUserTreeV2VO>> userMap) {
        //将人挂载到单位下面
        Map<String, UnitUserTreeV2VO> tmpUserMap = userMap.get(tree.getId());
        if (tmpUserMap != null && tmpUserMap.size() > 0) {
            tree.getChildren().addAll(tmpUserMap.values().stream().collect(Collectors.toList()));
        }

        //获取下级单位
        var data = orgs.stream().filter(t -> t.getParentNo().equalsIgnoreCase(parentId)).collect(Collectors.toList());
        if (data != null && data.size() > 0) {
            for (OrgVO t : data) {
                UnitUserTreeV2VO v2 = new UnitUserTreeV2VO();
                v2.setId(t.getId().toString()).setUserId("0")
                        .setParentId(t.getParentNo())
                        .setName(t.getOrgName());
                tree.getChildren().add(v2);
                packUser2TreeV2(v2, orgs, v2.getId(), userMap);
            }
        }
    }

    private List<UserVO> listUsers2PackTree() {
        //获取本地部门
        PageVo<UserSearch> pageVo = new PageVo<>();
        pageVo.setPageNum(1);
        pageVo.setPageSize(Integer.MAX_VALUE);
        pageVo.setParam(new UserSearch());
        //检索管理人员
        List<UserVO> users = this.userService.page(pageVo).getList();
        return users;
    }

    @Override
    public List<Object> packProcessUnitAndUser(int type) {
        List<UnitTreeVO> formOrg = new ArrayList<>();
        OrgSearch s = new OrgSearch();
        s.setParentNo("0");
        List<OrgVO> orgs = this.list(s);
        String json = JsonUtil.toJson(orgs);
        json = json.replaceAll("orgName", "name");
        formOrg = JSON.parseArray(json, UnitTreeVO.class);

        //检索管理人员
        List<UserVO> users = listUsers2PackTree();

        Map<String, List<UnitTreeVO>> mapUsersResult = mapUsers(users);
        packLocalUnitUser(formOrg, mapUsersResult, type);

        List<Object> result = new ArrayList<>();
        if (formOrg.size() > 0) {
            result.add(formOrg.get(0).getChild());
            if (users != null && users.size() > 0) {
                List<UnitTreeVO> list1 = new ArrayList<>();
                for (UserVO user : users) {
                    list1.add(new UnitTreeVO().setType("2").setId(user.getId().toString()).setName(user.getUserName()));
                }
                result.add(list1);
            }
        }
        return result;
    }

    private void packLocalUnitUser(List<UnitTreeVO> orgs, Map<String, List<UnitTreeVO>> user, int type) {
        for (UnitTreeVO org : orgs) {
            if (StringUtils.isEmpty(org.getType())) {
                org.setType("1");
            } else if (org.getType().equalsIgnoreCase("2")) {
                continue;
            }
            if (org.getChild() != null && org.getChild().size() > 0) {
                packLocalUnitUser(org.getChild(), user, type);
            } else if (org.getChild() == null) {
                org.setChild(new ArrayList<>());
            }
            if (type == 1) {
                var tmpUser = user.get(org.getId());
                if (tmpUser != null) {
                    org.getChild().addAll(tmpUser);
                }
            }
        }
    }

    private Map<String, List<UnitTreeVO>> mapUsers(List<UserVO> users) {
        Map<String, List<UnitTreeVO>> map = new HashMap<>();
        if (users != null && users.size() > 0) {
            for (UserVO user : users) {
                List<UserVO.UserUnits> units = user.getUnits();
                if (units != null && units.size() > 0) {
                    for (UserVO.UserUnits unit : units) {
                        List<UnitTreeVO> tmp = map.get(unit.getId());
                        if (tmp == null) {
                            tmp = new ArrayList<>();
                            map.put(unit.getId(), tmp);
                        }
                        tmp.add(new UnitTreeVO().setId(user.getId().toString()).setName(user.getUserName()).setType("2"));
                    }
                }
            }
        }
        return map;
    }

}
